package name.fowler.refactoring.simplestore.reports;

import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import name.fowler.refactoring.simplestore.BonusPointsCalculator;
import name.fowler.refactoring.simplestore.PriceCalculator;
import name.fowler.refactoring.simplestore.domain.Customer;
import name.fowler.refactoring.simplestore.domain.Movie;
import name.fowler.refactoring.simplestore.domain.Rental;

public class PriceReport implements Report {

    private Collection<Customer> customers;

    public PriceReport(Collection<Customer> customers) {
        this.customers = customers;
    }
    
    public PriceReport(Customer... customers) {
        this.customers = new LinkedList<Customer>(Arrays.asList(customers));
    }

    static List<List<String>> addRow(
    		List<List<String>> table,
    		String col1,
    		String col2,
    		String col3,
    		String col4)
    {
    	List<String> row = new LinkedList<String>(
    			Arrays.asList(new String[]{col1, col2, col3, col4}));
    	table.add(row);
		return table; 	
    }
	
    public String generate(Formatter formatter) {
    	
    	PriceCalculator priceCalculator = new PriceCalculator();
    	BonusPointsCalculator bonusPointsCalculator = new BonusPointsCalculator();
        
    	double totalPrice = 0; 	
        double customerSum;
        double rentalSum;
        double movieSum;
        
        // make price table
        List<List<String>> table = new LinkedList<List<String>>();

        // add column names
        table = addRow(table,
        		"Customer", "Rental", "Movie", "Sum");
        
        for (Customer customer : customers) {
        	table = addRow(table,
        			customer.getName(),
        			"", "", "");     	
            customerSum = 0;
            int rentalNum = 0;
            for (Rental rental : customer.getRentals()) {
            	rentalNum += 1;
            	table = addRow(table,
            			"", "#"+String.valueOf(rentalNum)+" ("+rental.getDaysRented()+" days)",
            			"", "");
                rentalSum = 0;
                for (Movie movie : rental.getMovies()) {
                    movieSum = priceCalculator.getPrice(movie, rental.getDaysRented());
                	table = addRow(table,
                			"", "",
                			movie.getTitle(), String.valueOf(movieSum));        	
                	rentalSum += movieSum;
                }
            	table = addRow(table,
            			"", "",
            			"Total",
            			String.valueOf(rentalSum));            	
            	customerSum += rentalSum;
            }
            table = addRow(table,
            		"",
            		"Total", "",
            		String.valueOf(customerSum));
            totalPrice += customerSum;
        }
    	table = addRow(table,
    			"Total",
    			"", "",
    			String.valueOf(totalPrice));
    	
    	// print
        formatter.init();
        formatter.addHeader("Prices report");
        formatter.addParagraph("Prices Table");
        formatter.addTable(table);
        
    	// print bonuses
    	formatter.addParagraph("Customer Bonuses");
    	int customerBonus;
    	for (Customer customer : customers) {
    		customerBonus = 0;
    		for (Rental rental : customer.getRentals()) {
    			for (Movie movie : rental.getMovies()) {
    				customerBonus += bonusPointsCalculator.getBonusPoints(movie, rental.getDaysRented());
    			}
    		}
			formatter.addLine("Customer " + customer.getName() + " bonuses: " + String.valueOf(customerBonus));
			formatter.addBreak();
    	}
    	formatter.addFooter("End of report");
    	formatter.finish();
    	
        return formatter.getResult();
    }
}
